package com.xjgz.aio.socket.buffer;

import java.nio.ByteBuffer;
import java.util.concurrent.ConcurrentLinkedQueue;

final class BufferPage {

    private boolean idle = true;

    private final ConcurrentLinkedQueue<VirtualBuffer> cleanBuffers = new ConcurrentLinkedQueue<>();

    private final boolean direct;

    BufferPage(boolean direct) {
        this.direct = direct;
    }

    public VirtualBuffer allocate(final int size) {
        if (size == 0) {
            throw new UnsupportedOperationException("cannot allocate zero bytes");
        }
 
        idle = false;

        VirtualBuffer virtualBuffer = cleanBuffers.poll();
        if (virtualBuffer != null && virtualBuffer.buffer().capacity() == size) {
            virtualBuffer.reset();
            return virtualBuffer;
        }

        if (virtualBuffer != null) {
            clean0(virtualBuffer);
        }

        return new VirtualBuffer(this, direct ? ByteBuffer.allocateDirect(size) : ByteBuffer.allocate(size));
    }

    public void clean(VirtualBuffer cleanBuffer) {
        cleanBuffers.offer(cleanBuffer);
    }

    public void tryClean() {
        if (!idle) {
            idle = true;
        } else {
            int count = 0;
            VirtualBuffer cleanBuffer;
            while (idle && count++ < 10 && (cleanBuffer = cleanBuffers.poll()) != null) {
                clean0(cleanBuffer);
            }
        }
    }

    private void clean0(VirtualBuffer virtualBuffer) {
        if (direct) {
            try {
                DirectBufferCleaner.clean(virtualBuffer.buffer());
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }

    public void release() {
        if (direct) {
            VirtualBuffer virtualBuffer;
            while ((virtualBuffer = cleanBuffers.poll()) != null) {
                clean0(virtualBuffer);
            }
        }
    }

    @Override
    public String toString() {
        return "BufferPage{direct=" + direct + " ,availableBuffers=" + cleanBuffers + '}';
    }
}
